/* 
 * Advanced Foundation Classes
 * Copyright (C) 2000/2004  Fabio Rotondo - Andrea Galimberti
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef AFC_EASYGUI_H
#define AFC_EASYGUI_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <gtk/gtk.h>
#include <gmodule.h>

#include "../afc.h"

/* AFC afc_easygui Magic Number */
#define AFC_EASYGUI_MAGIC ( 'E' << 24 | 'G' << 16 | 'U' << 8 | 'I' )

/* AFC afc_easygui Base value for constants */
#define AFC_EASYGUI_BASE 0x10000


/* Errors for afc_easygui */

#define AFC_EASYGUI_ERR_NO_GUI			AFC_EASYGUI_BASE + 1	/* No gui has been assigned, so there's nothing to do */
#define AFC_EASYGUI_ERR_NO_CONTAINER		AFC_EASYGUI_BASE + 2  /* No container is present to add a widget to */
#define AFC_EASYGUI_ERR_SYMBOL_UNKNOWN		AFC_EASYGUI_BASE + 3  /* the callback function specified is not defined in the current code */
#define AFC_EASYGUI_ERR_NO_PIXMAP		AFC_EASYGUI_BASE + 4  /* An error occurred while creating a pixmap */
#define AFC_EASYGUI_ERR_WIDGET_UNKNOWN		AFC_EASYGUI_BASE + 5  /* Widget name unknown */
#define AFC_EASYGUI_ERR_TREE_ITEM_TYPE		AFC_EASYGUI_BASE + 6  /* Wrong tree item type */
#define AFC_EASYGUI_ERR_FILE_NOT_FOUND		AFC_EASYGUI_BASE + 7  /* Cannot load a GUI definition from a file */
#define AFC_EASYGUI_ERR_WIDGET_DATA_NOT_FOUND	AFC_EASYGUI_BASE + 8  /* There is no "ewidget" field in vars */
#define AFC_EASYGUI_ERR_MENU_NOT_FOUND		AFC_EASYGUI_BASE + 9  /* No menu found in context with that name */


/* EasyGUIContainer types */

#define AFC_EASYGUI_CONTAINER_TYPE_WIDGET     	 0  /* It is just a widget, not a container */
#define AFC_EASYGUI_CONTAINER_TYPE_WINDOW     	 1  /* toplevel window */
#define AFC_EASYGUI_CONTAINER_TYPE_ROW        	 2  /* eg: rows, eqrows */
#define AFC_EASYGUI_CONTAINER_TYPE_COLUMN     	 3  /* eg: cols, eqcols */
#define AFC_EASYGUI_CONTAINER_TYPE_SCROLLEDW  	 4  /* scrolled window */
#define AFC_EASYGUI_CONTAINER_TYPE_TOOLBAR    	 5  /* toolbar */
#define AFC_EASYGUI_CONTAINER_TYPE_EVENTBOX   	 6  /* event box */
#define AFC_EASYGUI_CONTAINER_TYPE_FRAME  	 7  /* frame */
#define AFC_EASYGUI_CONTAINER_TYPE_TABS  	 8  /* Tabs */
#define AFC_EASYGUI_CONTAINER_TYPE_MENUBAR	 9  /* Menu Bar */
#define AFC_EASYGUI_CONTAINER_TYPE_MENU		10  /* Menu */
#define AFC_EASYGUI_CONTAINER_TYPE_OPTMENU	11  /* Menu */
#define AFC_EASYGUI_CONTAINER_TYPE_COMBO	12  /* Combo Container */

/* EasyGUIContainer is homogeneous? */

#define AFC_EASYGUI_CONTAINER_HOMOGENEOUS_NONE  0  /* no */
#define AFC_EASYGUI_CONTAINER_HOMOGENEOUS       1  /* yes */

/* Horientation For Label / Icons */
#define AFC_EASYGUI_HORIENT_RIGHT		0
#define AFC_EASYGUI_HORIENT_LEFT		1
#define AFC_EASYGUI_HORIENT_TOP			2
#define AFC_EASYGUI_HORIENT_BOTTOM		3

/* just some useful aliases */
#define AFC_EASYGUI_TAG_END				AFC_TAG_END
#define AFC_EASYGUI_ADD_HEAD				AFC_NODEMASTER_ADD_HEAD
#define AFC_EASYGUI_ADD_HERE				AFC_NODEMASTER_ADD_HERE
#define AFC_EASYGUI_ADD_TAIL				AFC_NODEMASTER_ADD_TAIL
#define AFC_EASYGUI_ARG_END				AFC_DYNAMIC_CLASS_ARG_END

/* TAG names for attributes */
#define AFC_EASYGUI_ARG_NODEMASTER  AFC_EASYGUI_BASE + 1
#define AFC_EASYGUI_ARG_NAME        AFC_EASYGUI_BASE + 2

/* TAGS */
#define AFC_EASYGUI_TAG_DELIMITERS	AFC_EASYGUI_BASE + 1	// Delimiter for strings containing values for eg combo box ("item 1|Item 2|Item 3")
#define AFC_EASYGUI_TAG_ESCAPE_CHAR	AFC_EASYGUI_BASE + 2	// Escape char for splitting
// #define AFC_EASYGUI_TAG_USER_DATA	AFC_EASYGUI_BASE + 3	// User Data

/* Various Constants */
#define AFC_EASYGUI_CONTEXT_MAIN	"_main"			

/******************
      EASYGUI
*******************/

struct afc_easygui;
typedef struct afc_easygui EasyGUI;

// DEPRECATED
// This stuff should go somewhere else
/*
struct afc_easygui_tree_item
{
	int type;
	char * label;
	char * path;
	NodeMaster * subtree;
	GtkSignalFunc select;
	GtkSignalFunc deselect;
	GtkSignalFunc toggle;
	GtkSignalFunc expand;
	GtkSignalFunc collapse;

	void * userdata;
};

typedef struct afc_easygui_tree_item EasyGUITreeItem;
*/

struct afc_easygui_widget_data
{
	GtkWidget * gtk_handle;		// Handler for gtk_container_add() operations
	int type;			// Type of the container (see AFC_EASYGUI_CONTAINER_TYPE_*)
	int homogeneous;
	DynamicClass * dc;		// Dynamic Class rappresenting the current container
	EasyGUI * egui;
};

typedef struct afc_easygui_widget_data EasyGUIWidgetData;

struct afc_easygui_menu_item
{
	char * path;
	char * type;
	char * callback_name;
	char * accelerator;
};

typedef struct afc_easygui_menu_item EasyGUIMenuItem;


// This structure contains common data
// To be shared between all EasyGUIContext instances without
// re-allocating it.
struct afc_easygui_internal_data
{
	char * delimiters;		// Chars delimiters for strings
	GModule * local;		// Local instance of GModule
	StringNode * snode;		// Used for splitting operations during GUI parsing
	CommandParser * parser;		// GUI Parser
};

typedef struct afc_easygui_internal_data EasyGUIInternalData;

// All data related to a single window (context) of EasyGUI
struct afc_easygui_context
{
	EasyGUI * egui;
	EasyGUIWidgetData * curr_container;

	char 	   * name;		// Name of the Context
	char	   * gui;		// GUI Definition

	GtkWidget  * win;		// The Window
	NodeMaster * containers;	// List of containers
	Dictionary * widgets;		// Widgets in the window
	Dictionary * radiogroups;	// Radio Groups in window
	Dictionary * menus;		// Menus instantiated by the app

	void * userdata;

	EasyGUIInternalData * int_data;

	short	     main_win;		// Flag T/F. If True, it is a main window and will close all the other wins when closed.
};

typedef struct afc_easygui_context EasyGUIContext;


struct afc_easygui_default_params
{
	char * name;
	short  expand;
	short  fill;
	char * tip;
	char * longtip;
	int    space;
	int    border;
	char * tab_title;
	char * tab_icon;
	char * info;

	char * key_events;		// Standard Key Press / Release events
};

typedef struct afc_easygui_default_params EasyGUIDefaultParams;


struct afc_easygui 
{
	unsigned long magic;
	char 		     * gui;
	EasyGUIContext	     * curr_context;
	CommandParser 	     * parser;		// Parser for the GUI definition
	Dictionary	     * contexts;	// Keeps in memory all Contexts
	DynamicClassMaster   * commands;	// All GUI widgets are stored here
	EasyGUIDefaultParams * def_params;
	EasyGUIInternalData  * int_data;	// EasyGUI specific data

	Dictionary 	     * dnd_targets;		// DND Target Entries
	BOOL		       dnd_targets_changed;	// Flag T/F indicating targets have changed

	GtkIconFactory * icons;			// GtkIconFactory to hold icons for menus/buttons/toolbars/...
	GtkTooltips    * tips;  		// GtkTooltips to hold tooltips from widgets
	GtkTargetEntry * dnd_entries;		// GtkTargetEntries
};

typedef int ( * EasyGUISignalFunc ) ( DynamicClass * dc, EasyGUIContext * context );
typedef int ( * EasyGUIKeyFunc )    ( DynamicClass * dc, EasyGUIContext * context, int key_val, short pressed );

struct afc_easygui_dnd_target_item
{
	char * name;
	int    flags;
	int    info;
};

typedef struct afc_easygui_dnd_target_item EasyGUIDNDTargetItem;

/* functions */

// EasyGUI * afc_easygui_new ( AFC * afc );
EasyGUI * afc_easygui_new ();
#define afc_easygui_delete(eg) if ( eg ) { _afc_easygui_delete ( eg ); eg = NULL; }
int _afc_easygui_delete ( EasyGUI * ) ;
int afc_easygui_clear ( EasyGUI * ) ;
int afc_easygui_init ( EasyGUI * );
int afc_easygui_main ( EasyGUI * );
int afc_easygui_context_show ( EasyGUIContext * context );
int afc_easygui_preload_icon ( EasyGUI * easygui, const char * filename );
GtkWidget * afc_easygui_load_icon ( EasyGUI * easygui, const char * filename, int size );

int afc_easygui_get_icon ( EasyGUI * easygui, GtkWidget * icon, const char * filename, int size );
int afc_easygui_set_tip ( EasyGUI * easygui, GtkWidget * widget, const char * tip, const char * long_tip );
DynamicClass * afc_easygui_get_class_instance ( EasyGUI *, char * );
int afc_easygui_execute ( EasyGUI * easygui, char * wname, char * method, ... );

#define afc_easygui_set_tags(egui,first,...) _afc_easygui_set_tags ( egui, first, ## __VA_ARGS__, AFC_TAG_END )
int _afc_easygui_set_tags ( EasyGUI * easygui, int first_tag, ... );
int afc_easygui_set_tag  ( EasyGUI * easygui, int tag, void * val );

EasyGUIContext * afc_easygui_add_context ( EasyGUI * easygui, char * context_name );
int afc_easygui_widget_execute ( EasyGUIContext * context, char * wname, char * method, ... );

// Context Functions
EasyGUIContext * afc_easygui_context_new ( EasyGUI * easygui, const char * context_name );
int afc_easygui_context_delete ( EasyGUIContext * context );
int afc_easygui_context_del ( void * con );
int afc_easygui_context_del_widget ( void * dc );
int afc_easygui_context_set_gui ( EasyGUIContext * context, const char * gui);
int afc_easygui_context_set_gui_from_file ( EasyGUIContext * context, const char * filename );

int afc_easygui_context_set_menu ( EasyGUIContext * context, GtkWidget * menu );
// DynamicClass * afc_easygui_context_get_widget ( EasyGUIContext * context, char * wname );
#define afc_easygui_context_get_widget(context,wname)	afc_dictionary_get ( context->widgets, wname )
int afc_easygui_context_add_container ( EasyGUIContext * context, GtkWidget * w, DynamicClass * dc, int type, int homogeneous );
int afc_easygui_context_close_container ( EasyGUIContext * context );
int afc_easygui_widget_register ( EasyGUIContext * context, GtkWidget * w, DynamicClass * dc );

int afc_easygui_add_dnd_target ( EasyGUI * egui, const char * name, int flags, int info );

/*** internal functions: do not call! ***/
int afc_easygui_internal_add_widget ( EasyGUIContext * context, GtkWidget * w, DynamicClass * dc );

int afc_easygui_internal_widget_data_delete ( EasyGUIWidgetData * );
#endif
